﻿using System;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestByWire.Test.Fakes;

namespace TestByWire.Test
{
    [TestClass]
    public class UseStubLateBoundIntegrationTest : TestTarget<Computer>
    {
        [TestMethod]
        [UseStubLateBound(typeof(ICalculate2), "_anotherCalculator")]
        public void MustBeAbleToLateBindStub()
        {
            var lateBoundCalculator = When.Calling.GetLateBoundCalculator();

            Assert.IsNotNull(lateBoundCalculator);
        }

        [TestMethod]
		[UseStubLateBound(typeof(ICalculate2), "_anotherCalculator")]
		[UseStubLateBound(typeof(ICalculate2), "_yetAnotherCalculator")]
        public void MustBeAbleToLateBindMultipleSameTypeStubs()
        {
            var target = When.Calling;
            var lateBoundStub = target.GetLateBoundCalculator();
            var anotherLateBoundStub = target.GetYeatAnotherLateBoundCalculator();

            Assert.IsNotNull(lateBoundStub);
            Assert.IsNotNull(anotherLateBoundStub);
            Assert.AreNotEqual(lateBoundStub, anotherLateBoundStub);
        }

        [TestMethod]
		[UseStubLateBound(typeof(ICalculate2), "_anotherCalculator")]
		[UseStubLateBound(typeof(ICalculate2), "_yetAnotherCalculator")]
        public void LateBindingTwoStubOfSameTypeWithoutRegistrationOnNameMustFail()
        {
            AssertEx.Throws<InvalidOperationException>(() => When.Calling.Calculator.Add(2, 2));
        }

        [TestMethod]
		[UseStubLateBound(typeof(ICalculate2), "_anotherCalculator")]
		[UseStubLateBound(typeof(ICalculate2), "_yetAnotherCalculator", typeof(Calculate2Stub))]
        public void LateBindingTwoStubOfSameTypeWhereOneIsAManualStubMustNotFail()
        {
            var target = When.Calling;
            var stub = target.GetLateBoundCalculator();
            var realStub = target.GetYeatAnotherLateBoundCalculator();

            Assert.IsNotNull(stub);
            Assert.IsInstanceOfType(realStub, typeof(Calculate2Stub));
        }

        [TestMethod]
		[UseStubLateBound(typeof(ICalculate2), "_anotherCalculator", typeof(Calculate2Stub))]
		[UseStubLateBound(typeof(ICalculate2), "_yetAnotherCalculator", typeof(Calculate2Stub))]
        public void LateBindingTwoStubOfSameTypeWhereBothAreManualStubsMustPointToDifferentInstances()
        {
            var target = When.Calling;
            var realStubOne = target.GetLateBoundCalculator();
            var realStubTwo = target.GetYeatAnotherLateBoundCalculator();

            Assert.IsNotNull(realStubOne);
            Assert.IsNotNull(realStubTwo);
            Assert.AreNotEqual(realStubOne, realStubTwo);
        }
    }
}
